using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;

namespace Felbot.Interface {
    // Felbot.Interface.MdiTabStrip:
    //  Source:
    //   CODEPROJECT.COM ARTICLE
    //   "Easy Tabbed Mdi Interface Using the ToolStrip"
    //   By beep
    //   http://www.codeproject.com/KB/toolbars/MdiTabToolStrip.aspx
    //
    //  Modifications:
    //   Ribose (nmBook):
    //    Cleaned up excessiveness, added hover colors, removed close button colors (made same as text colors)

    /// <summary>
    /// A special ToolStrip for tracking Mdi children in an Mdi parent form.
    /// </summary>
    public class MdiTabStrip : ToolStrip {
        #region State
        private Color m_ActiveForeColor = SystemColors.ControlText;
        private Color m_HoverForeColor = SystemColors.HighlightText;
        private Color m_InactiveForeColor = SystemColors.GrayText;
        private Color m_ActiveBackColor = SystemColors.ControlLight;
        private Color m_HoverBackColor = SystemColors.Highlight;
        private Color m_InactiveBackColor = SystemColors.ControlDark;
        private Color m_ActiveBorderColor = SystemColors.ActiveBorder;
        private Color m_HoverBorderColor = SystemColors.InactiveBorder;
        private Color m_InactiveBorderColor = SystemColors.InactiveBorder;
        private bool m_ActiveIsBold = true;
        private bool m_DrawBorder = true;
        private MdiTabStripButton m_SelectedTab;
        #endregion //--State

        #region Construction
        /// <summary>
        /// Constructs a new TabStrip with default values.
        /// </summary>
        public MdiTabStrip() {
            InitializeComponent();
            this.
            Renderer = new ToolStripSystemRenderer();
        }

        #region Designer
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent() {
            components = new System.ComponentModel.Container();
        }
        #endregion
        #endregion
        #endregion //--Construction

        #region Private and Protected Members
        /// <summary>
        /// Creates and returns a new MdiTabStripButton. You can override
        /// this method to return a derived version of MdiTabStripButton if
        /// you wish.
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        protected virtual MdiTabStripButton CreateMdiButton(Form f) {
            return new MdiTabStripButton(f);
        }

        /// <summary>
        /// Event handler hooked to MdiChildActivate event.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMdiChildActivate(object sender, EventArgs e) {
            Form f = sender as Form;
            AddMdiChild(f.ActiveMdiChild);
            OnFormMdiChildActivate(f.ActiveMdiChild);
        }

        /// <summary>
        /// Called when a form is activated by the Mdi parent form.
        /// </summary>
        /// <param name="activeForm"></param>
        protected virtual void OnFormMdiChildActivate(Form activeForm) { }
        #endregion //--Private and Protected Members

        #region Overrides
        /// <summary>
        /// Overridden. Hooks to the Mdi form's MdiChildActivate event.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnHandleCreated(EventArgs e) {
            base.OnHandleCreated(e);
            Form mdiForm = FindForm();
            if (null != mdiForm && mdiForm.IsMdiContainer)
                mdiForm.MdiChildActivate += new EventHandler(FormMdiChildActivate);
        }

        /// <summary>
        /// Overridden. Unhooks the Mdi form when destroyed.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnHandleDestroyed(EventArgs e) {
            base.OnHandleDestroyed(e);
            Form mdiForm = FindForm();
            if (null != mdiForm && mdiForm.IsMdiContainer)
                mdiForm.MdiChildActivate -= new EventHandler(FormMdiChildActivate);
        }

        /// <summary>
        /// Overridden. Disallows anything but TabStripButton.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnItemAdded(ToolStripItemEventArgs e) {
            if (!(e.Item is MdiTabStripButton)) {
                Items.Remove(e.Item);

                return;
            }
            base.OnItemAdded(e);
        }

        /// <summary>
        /// Shadowed to disallow property setter.
        /// </summary>
        [Browsable(false)]
        public new ToolStripRenderMode RenderMode {
            get { return ToolStripRenderMode.Custom; }
            set { }
        }

        /// <summary>
        /// Shadowed to disallow property setter.
        /// </summary>
        [Browsable(false)]
        public new ToolStripGripStyle GripStyle {
            get { return ToolStripGripStyle.Hidden; }
            set { base.GripStyle = ToolStripGripStyle.Hidden; }
        }

        /// <summary>
        /// Overridden to hide from property browser.
        /// </summary>
        [Browsable(false)]
        public override ToolStripItemCollection Items {
            get { return base.Items; }
        }
        #endregion //--Overrides

        #region Public Interface
        /// <summary>
        /// Gets or sets the forecolor for the active tab.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "ControlText")]
        public Color ActiveForeColor {
            get { return m_ActiveForeColor; }
            set {
                if (value == ActiveForeColor)
                    return;

                m_ActiveForeColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the forecolor for hovered over tabs.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "HighlightText")]
        public Color HoverForeColor {
            get { return m_HoverForeColor; }
            set {
                if (value == HoverForeColor)
                    return;

                m_HoverForeColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the forecolor for inactive tabs.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "GrayText")]
        public Color InactiveForeColor {
            get { return m_InactiveForeColor; }
            set {
                if (value == InactiveForeColor)
                    return;

                m_InactiveForeColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the backcolor for the active tab.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "ControlLight")]
        public Color ActiveBackColor {
            get { return m_ActiveBackColor; }
            set {
                if (value == ActiveBackColor)
                    return;

                m_ActiveBackColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the backcolor for hovered over tabs.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "Highlight")]
        public Color HoverBackColor {
            get { return m_HoverBackColor; }
            set {
                if (value == HoverBackColor)
                    return;

                m_HoverBackColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the backcolor for inactive tabs.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "ControlDark")]
        public Color InactiveBackColor {
            get { return m_InactiveBackColor; }
            set {
                if (value == InactiveBackColor)
                    return;

                m_InactiveBackColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the border color for the active tab.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "ActiveBorder")]
        public Color ActiveBorderColor {
            get { return m_ActiveBorderColor; }
            set {
                if (value == ActiveBorderColor)
                    return;

                m_ActiveBorderColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the border color for hovered over tabs.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "InactiveBorder")]
        public Color HoverBorderColor {
            get { return m_HoverBorderColor; }
            set {
                if (value == HoverBorderColor)
                    return;

                m_HoverBorderColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the border color for inactive tabs.
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(Color), "InactiveBorder")]
        public Color InactiveBorderColor {
            get { return m_InactiveBorderColor; }
            set {
                if (value == InactiveBorderColor)
                    return;

                m_InactiveBorderColor = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets whether to use bold text for active tab.
        /// </summary>
        [Category("Appearance"), DefaultValue(true)]
        public bool ActiveIsBold {
            get { return m_ActiveIsBold; }
            set {
                if (value == ActiveIsBold)
                    return;

                m_ActiveIsBold = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets whether to draw a border on the tab.
        /// </summary>
        [Category("Appearance"), DefaultValue(true)]
        public bool DrawBorder {
            get { return m_DrawBorder; }
            set {
                if (value == DrawBorder)
                    return;

                m_DrawBorder = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the selected tab.
        /// </summary>
        [Browsable(false)]
        public MdiTabStripButton SelectedTab {
            get { return m_SelectedTab; }
            set {
                if (null == value || !Equals(value.Owner))
                    return;

                if (value.Equals(m_SelectedTab))
                    return;

                m_SelectedTab = value;
                foreach (MdiTabStripButton tsb in Items) {
                    tsb.Font = Font;
                    tsb.Invalidate();
                }
                if (ActiveIsBold)
                    m_SelectedTab.Font = new Font(Font, FontStyle.Bold);
                OnItemClicked(new ToolStripItemClickedEventArgs(value));
            }
        }

        /// <summary>
        /// Finds a tab from a Form.
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public MdiTabStripButton FindTab(Form f) {
            if (null == f)
                return null;

            foreach (MdiTabStripButton tsb in Items) {
                if (f.Equals(tsb.GetMdiChild()))
                    return tsb;
            }

            return null;
        }

        /// <summary>
        /// Gets a value indicating if the Form can be found in any of the tabs.
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public bool ContainsMdiChild(Form f) {
            if (null == f)
                return false;

            foreach (MdiTabStripButton tsb in Items) {
                if (f.Equals(tsb.GetMdiChild()))
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Adds a tab with the given Form. If the Form is already in the
        /// tab collection, it just selects the tab.
        /// </summary>
        /// <param name="f"></param>
        public void AddMdiChild(Form f) {
            if (null == f)
                return;

            if (!f.Text.StartsWith("Profile")) //felbot profiles only!
                return;

            MdiTabStripButton tsb = FindTab(f);
            if (null != tsb)
                SelectedTab = tsb;
            else {
                tsb = CreateMdiButton(f);
                Items.Add(tsb);
                SelectedTab = tsb;
            }
        }
        #endregion //--Public Interface
    }
}
